package com.solo.codegen.service.inner;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.text.NamingCase;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.engine.velocity.VelocityEngine;
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
import com.solo.codegen.api.entity.GenModule;
import com.solo.common.core.consts.Symbols;
import com.solo.common.core.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class ModuleEngine {

    private final TemplateEngine templateEngine;

    /**
     * 初始化 TemplateEngine 属性
     */
    public ModuleEngine() {
        TemplateConfig config = new TemplateConfig();
        config.setResourceMode(TemplateConfig.ResourceMode.CLASSPATH);
        this.templateEngine = new VelocityEngine(config);
    }

    public Map<String, String> execute(GenModule module) {
        String artifactId = module.getArtifactId();
        
        Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(ModuleEngine.Template.values().length); // 有序
        Dict dict = Dict.create();
        dict.set("module", module);
        List<String> artifactIdList = StrUtil.split(module.getArtifactId(), "-");
        String name = StrUtil.blankToDefault(artifactIdList.get(1), artifactIdList.get(0));
        String importPackage = module.getGroupId() + Symbols.DOT + name;
        String mainName = StrUtil.upperFirst(StrUtil.format("{}Application", NamingCase.toCamelCase(artifactId, '-')));
        dict.set("importPackage", importPackage);
        dict.set("mainName", mainName);
        for (ModuleEngine.Template template : ModuleEngine.Template.values()) {
            String templatePath = template.getTemplatePath();
            result.put(buildPath(template, module), templateEngine.getTemplate(templatePath).render(dict));
        }
        return result;
    }

    private String buildPath(Template template, GenModule module) {
        Map<String, String> map = new HashMap<>();
        map.put("artifactId", module.getArtifactId());
        map.put("module", StringUtils.format(template.getModule(), map));
        map.put("packagePath", template.getPackagePath());
        map.put("fileName", getFileName(template, module));
        return StringUtils.format("{artifactId}/{module}{packagePath}/{fileName}", map);
    }

    private String getFileName(Template template, GenModule module) {
        String templatePath = template.getTemplatePath();
        String artifactId = module.getArtifactId();
        String mainName = FileUtil.mainName(templatePath);
        return switch (template) {
            case JAVA_APPLICATION -> {
                String groupId = module.getGroupId();
                List<String> artifactIdList = StrUtil.split(artifactId, "-");
                String name = StrUtil.blankToDefault(artifactIdList.get(1), artifactIdList.get(0));
                String packagePath = StrUtil.replace(groupId, Symbols.DOT, Symbols.SLASH) + Symbols.SLASH + name;
                mainName = StrUtil.format("{}Application.java", NamingCase.toCamelCase(artifactId, '-'));
                yield StrUtil.format("/{}/{}", packagePath, StrUtil.upperFirst(mainName));
            }
            default -> StrUtil.format("/{}", mainName);
        };
    }

    @Getter
    @AllArgsConstructor
    private enum Template {

        POM("codegen/module/pom.xml.vm", "", ""),
        API_POM("codegen/module/api/pom.xml.vm", "{artifactId}-api", ""),
        BIZ_POM("codegen/module/biz/pom.xml.vm", "{artifactId}-biz", ""),
        JAVA_APPLICATION("codegen/module/biz/java/application.java.vm", "{artifactId}-biz", "/src/main/java"),
        RESOURCES_APPLICATION("codegen/module/biz/resources/application.yml.vm", "{artifactId}-biz", "/src/main/resources");
        
        /**
         * 模版路径
         */
        private final String templatePath;

        /**
         * 所属模块
         */
        private final String module;

        /**
         * 部分包路径
         */
        private final String packagePath;

    }

}
